<html>
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<head>
<title>Section 8.11.&nbsp; Changing User IDs and Group IDs</title>
<link rel="STYLESHEET" type="text/css" href="images/style.css">
<link rel="STYLESHEET" type="text/css" href="images/docsafari.css">
</head>
<body>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/team.gif" width="60" height="17" border="0" align="absmiddle"  alt="Team BBL"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=ch08lev1sec10.html><img src="images/prev.gif" width="60" height="17" border="0" align="absmiddle" alt="Previous Page"></a>
<a href=ch08lev1sec12.html><img src="images/next.gif" width="60" height="17" border="0" align="absmiddle" alt="Next Page"></a>
</div></td></tr></table>
<br><table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td valign="top"><a name="ch08lev1sec11"></a>
<h3 class="docSection1Title">8.11. Changing User IDs and Group IDs</h3>
<p class="docText">In the UNIX System, privileges, such as being able to change the system's notion of the current date, and access control, such as being able to read or write a particular file, are based on user and group IDs. When our programs need additional privileges or need to gain access to resources that they currently aren't allowed to access, they need to change their user or group ID to an ID that has the appropriate privilege or access. Similarly, when our programs need to lower their privileges or prevent access to certain resources, they do so by changing either their user ID or group ID to an ID without the privilege or ability access to the resource.</P>
<p class="docText">In general, we try to use the <span class="docEmphasis">least-privilege</span> model when we design our applications. Following this model, our programs should use the least privilege necessary to accomplish any given task. This reduces the likelihood that security can be compromised by a malicious user trying to trick our programs into using their privileges in unintended ways.</P>
<p class="docText">We can set the real user ID and effective user ID with the <tt>setuid</tt> function. Similarly, we can set the real group ID and the effective group ID with the <tt>setgid</tt> function.</p>
<a name="inta288"></a><P><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="500"></colgroup><thead></thead><TR><TD class="docTableCell" align="left" valign="top"><p class="docText">
<pre>
#include &lt;unistd.h&gt;

int setuid(uid_t <span class="docEmphItalicAlt">uid</span>);

int setgid(gid_t <span class="docEmphItalicAlt">gid</span>);
</pre><br>
</P></TD></TR><tr><TD class="docTableCell" align="right" valign="top"><p class="docText">Both return: 0 if OK, 1 on error</p></TD></TR></table></P><br>
<p class="docText">There are rules for who can change the IDs. Let's consider only the user ID for now. (Everything we describe for the user ID also applies to the group ID.)</P>
<div style="font-weight:bold"><ol class="docList" type="1"><LI><div style="font-weight:normal"><p class="docList"><a name="idd1e58293"></a><a name="idd1e58298"></a><a name="idd1e58303"></a><a name="idd1e58308"></a><a name="idd1e58313"></a><a name="idd1e58318"></a><a name="idd1e58323"></a><a name="idd1e58328"></a><a name="idd1e58333"></a><a name="idd1e58336"></a><a name="idd1e58341"></a>If the process has superuser privileges, the <tt>setuid</tt> function sets the real user ID, effective user ID, and saved set-user-ID to <span class="docEmphasis">uid</span>.</p></div></LI><LI><div style="font-weight:normal"><p class="docList">If the process does not have superuser privileges, but <span class="docEmphasis">uid</span> equals either the real user ID or the saved set-user-ID, <tt>setuid</tt> sets only the effective user ID to <span class="docEmphasis">uid</span>. The real user ID and the saved set-user-ID are not changed.</p></div></li><li><div style="font-weight:normal"><p class="docList">If neither of these two conditions is true, <tt>errno</tt> is set to <tt>EPERM</tt>, and 1 is returned.</p></div></LI></ol></div>
<p class="docText">Here, we are assuming that <tt>_POSIX_SAVED_IDS</tt> is true. If this feature isn't provided, then delete all preceding references to the saved set-user-ID.</p>
<blockquote>
<p class="docText">The saved IDs are a mandatory feature in the 2001 version of POSIX.1. They used to be optional in older versions of POSIX. To see whether an implementation supports this feature, an application can test for the constant <tt>_POSIX_SAVED_IDS</tt> at compile time or call <tt>sysconf</tt> with the <tt>_SC_SAVED_IDS</tt> argument at runtime.</P>
</blockquote>
<p class="docText">We can make a few statements about the three user IDs that the kernel maintains.</p>
<div style="font-weight:bold"><ol class="docList" type="1"><LI><div style="font-weight:normal"><p class="docList">Only a superuser process can change the real user ID. Normally, the real user ID is set by the <tt>login</tt>(1) program when we log in and never changes. Because <tt>login</tt> is a superuser process, it sets all three user IDs when it calls <tt>setuid</tt>.</p></div></li><li><div style="font-weight:normal"><p class="docList">The effective user ID is set by the <tt>exec</tt> functions only if the set-user-ID bit is set for the program file. If the set-user-ID bit is not set, the <tt>exec</tt> functions leave the effective user ID as its current value. We can call <tt>setuid</tt> at any time to set the effective user ID to either the real user ID or the saved set-user-ID. Naturally, we can't set the effective user ID to any random value.</p></div></li><li><div style="font-weight:normal"><p class="docList">The saved set-user-ID is copied from the effective user ID by <tt>exec</tt>. If the file's set-user-ID bit is set, this copy is saved after <tt>exec</tt> stores the effective user ID from the file's user ID.</p></div></li></ol></div>
<p class="docText"><a class="docLink" href="#ch08fig18">Figure 8.18</a> summarizes the various ways these three user IDs can be changed.</p>
<a name="ch08fig18"></a><p><table cellspacing="0" class="allBorders" border="1" RULES="groups" cellpadding="5"><caption><h5 class="docTableTitle">Figure 8.18. Ways to change the three user IDs</h5></caption><colgroup><col width="100"><col width="100"><col width="100"><col width="100"><col width="100"></colgroup><thead><tr><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="top" rowspan="2"><p class="docText"><span class="docEmphRoman">ID</span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="bottom" colspan="2"><p class="docText"><span class="docEmphRoman"><tt>exec</tt></span></p></th><th class="bottomBorder thead" scope="col" align="center" valign="bottom" colspan="2"><p class="docText"><span class="docEmphRoman"><tt>setuid</tt>(<span class="docEmphasis"><tt>uid</tt></span><tt>)</tt></span></p></th></tr><TR><th class="rightBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">set-user-ID bit off</span></P></th><th class="rightBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">set-user-ID bit on</span></p></th><th class="rightBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">superuser</span></P></th><th class="thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">unprivileged user</span></P></th></TR></thead><tr><TD class="rightBorder" align="left" valign="top"><p class="docText">real user ID</P></TD><td class="rightBorder" align="left" valign="top"><p class="docText">unchanged</P></td><TD class="rightBorder" align="left" valign="top"><p class="docText">unchanged</P></TD><td class="rightBorder" align="left" valign="top"><p class="docText">set to <span class="docEmphasis">uid</span></P></TD><td class="docTableCell" align="left" valign="top"><p class="docText">unchanged</P></TD></tr><tr><td class="rightBorder" align="left" valign="top"><p class="docText">effective user ID</p></TD><td class="rightBorder" align="left" valign="top"><p class="docText">unchanged</P></td><TD class="rightBorder" align="left" valign="top"><p class="docText">set from user ID of program file</p></td><td class="rightBorder" align="left" valign="top"><p class="docText">set to <span class="docEmphasis">uid</span></p></td><td class="docTableCell" align="left" valign="top"><p class="docText">set to <span class="docEmphasis">uid</span>
</p></td></tr><tr><td class="rightBorder" align="left" valign="top"><p class="docText">saved set-user ID</p></td><td class="rightBorder" align="left" valign="top"><p class="docText">copied from effective user ID</p></td><td class="rightBorder" align="left" valign="top"><p class="docText">copied from effective user ID</P></TD><td class="rightBorder" align="left" valign="top"><p class="docText">set to <span class="docEmphasis">uid</span></P></TD><TD class="docTableCell" align="left" valign="top"><p class="docText">unchanged</p></TD></TR></table></P><br>
<p class="docText">Note that we can obtain only the current value of the real user ID and the effective user ID with the functions <tt>getuid</tt> and <tt>geteuid</tt> from <a class="docLink" href="ch08lev1sec2.html#ch08lev1sec2">Section 8.2</a>. We can't obtain the current value of the saved set-user-ID.</P>
<a name="ch08ex07"></a>
<h5 class="docExampleTitle">Example</H5>
<p class="docText"><a name="idd1e58625"></a>To see the utility of the saved set-user-ID feature, let's examine the operation of a program that uses it. We'll look at the <tt>man</tt>(1) program, which is used to display online manual pages. The <tt>man</tt> program can be installed either set-user-ID or set-group-ID to a specific user or group, usually one reserved for <tt>man</tt> itself. The <tt>man</tt> program can be made to read and possibly overwrite files in locations that are chosen either through a configuration file (usually <tt>/etc/man.config</tt> or <tt>/etc/manpath.config</tt>) or using a command-line option.</P>
<p class="docText">The <tt>man</tt> program might have to execute several other commands to process the files containing the manual page to be displayed. To prevent being tricked into running the wrong commands or overwriting the wrong files, the <tt>man</tt> command has to switch between two sets of privileges: those of the user running the <tt>man</tt> command and those of the user that owns the <tt>man</tt> executable file. The following steps take place.</P>
<div style="font-weight:bold"><ol class="docList" type="1"><li><div style="font-weight:normal"><p class="docList">Assuming that the <tt>man</tt> program file is owned by the user name <tt>man</tt> and has its set-user-ID bit set, when we <tt>exec</tt> it, we have</P><p class="docText"><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;real&nbsp;user&nbsp;ID&nbsp;=&nbsp;our&nbsp;user&nbsp;ID<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;effective&nbsp;user&nbsp;ID&nbsp;=&nbsp;<tt>man</tt><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;saved&nbsp;set-user-ID&nbsp;=&nbsp;<tt>man</tt><BR></p></div></li><li><div style="font-weight:normal"><p class="docList">The <tt>man</tt> program accesses the required configuration files and manual pages. These files are owned by the user name <tt>man</tt>, but because the effective user ID is <tt>man</tt>, file access is allowed.</p></div></LI><li><div style="font-weight:normal"><p class="docList">Before <tt>man</tt> runs any command on our behalf, it calls <tt>setuid(getuid())</tt>. Because we are not a superuser process, this changes only the effective user ID. We have</P><p class="docText"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;real&nbsp;user&nbsp;ID&nbsp;=&nbsp;our&nbsp;user&nbsp;ID&nbsp;(unchanged)<BR>&nbsp;&nbsp;&nbsp;effective&nbsp;user&nbsp;ID&nbsp;=&nbsp;our&nbsp;user&nbsp;ID<br>&nbsp;saved&nbsp;set-user-ID&nbsp;=&nbsp;<tt>man</tt>&nbsp;(unchanged)<br></p><p class="docList">Now the <tt>man</tt> process is running with our user ID as its effective user ID. This means that we can access only the files to which we have normal access. We have no additional permissions. It can safely execute any filter on our behalf.</p></div></li><li><div style="font-weight:normal"><p class="docList">When the filter is done, <tt>man</tt> calls <tt>setuid(</tt><span class="docEmphasis">euid</span><tt>)</tt>, where <span class="docEmphasis">euid</span> is the numerical user ID for the user name <tt>man</tt>. (This was saved by <tt>man</tt> by calling <tt>geteuid</tt>.) This call is allowed because the argument to <tt>setuid</tt> equals the saved set-user-ID. (This is why we need the saved set-user-ID.) Now we have</p><p class="docText"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;real&nbsp;user&nbsp;ID&nbsp;=&nbsp;our&nbsp;user&nbsp;ID&nbsp;(unchanged)<br>&nbsp;&nbsp;&nbsp;effective&nbsp;user&nbsp;ID&nbsp;=&nbsp;<tt>man</tt><br>&nbsp;saved&nbsp;set-user-ID&nbsp;=&nbsp;<tt>man</tt>&nbsp;(unchanged)<br></p></div></li><li><div style="font-weight:normal"><p class="docList">The <tt>man</tt> program can now operate on its files, as its effective user ID is <tt>man</tt>.</p></div></li></ol></div>
<p class="docText">By using the saved set-user-ID in this fashion, we can use the extra privileges granted to us by the set-user-ID of the program file at the beginning of the process and at the end <a name="idd1e58781"></a><a name="idd1e58784"></a><a name="idd1e58789"></a><a name="idd1e58794"></a><a name="idd1e58801"></a><a name="idd1e58806"></a><a name="idd1e58813"></a><a name="idd1e58816"></a>of the process. In between, however, the process runs with our normal permissions. If we weren't able to switch back to the saved set-user-ID at the end, we might be tempted to retain the extra permissions the whole time we were running (which is asking for trouble).</p>
<p class="docText">Let's look at what happens if <tt>man</tt> spawns a shell for us while it is running. (The shell is spawned using <tt>fork</tt> and <tt>exec</tt>.) Because the real user ID and the effective user ID are both our normal user ID (step 3), the shell has no extra permissions. The shell can't access the saved set-user-ID that is set to <tt>man</tt> while <tt>man</tt> is running, because the saved set-user-ID for the shell is copied from the effective user ID by <tt>exec</tt>. So in the child process that does the <tt>exec</tt>, all three user IDs are our normal user ID.</P>
<p class="docText">Our description of how <tt>man</tt> uses the <tt>setuid</tt> function is not correct if the program is set-user-ID to root, because a call to <tt>setuid</tt> with superuser privileges sets all three user IDs. For the example to work as described, we need <tt>setuid</tt> to set only the effective user ID.</P>

<a name="ch08lev2sec2"></a>
<h4 class="docSection2Title"><tt>setreuid</tt> and <tt>setregid</tt> Functions</H4>
<p class="docText">Historically, BSD supported the swapping of the real user ID and the effective user ID with the <tt>setreuid</tt> function.</P>
<a name="inta298"></a><P><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="500"></colgroup><thead></thead><tr><TD class="docTableCell" align="left" valign="top"><p class="docText">
<pre>
   #include &lt;unistd.h&gt;

   int setreuid(uid_t <span class="docEmphItalicAlt">ruid</span>, uid_t <span class="docEmphItalicAlt">euid</span>);

   int setregid(gid_t <span class="docEmphItalicAlt">rgid</span>, gid_t <span class="docEmphItalicAlt">egid</span>);
</pre><BR>

</P></td></TR><tr><TD class="docTableCell" align="right" valign="top"><p class="docText">Both return: 0 if OK, 1 on error</P></TD></tr></table></P><BR>
<p class="docText">We can supply a value of 1 for any of the arguments to indicate that the corresponding ID should remain unchanged.</p>
<p class="docText">The rule is simple: an unprivileged user can always swap between the real user ID and the effective user ID. This allows a set-user-ID program to swap to the user's normal permissions and swap back again later for set-user-ID operations. When the saved set-user-ID feature was introduced with POSIX.1, the rule was enhanced to also allow an unprivileged user to set its effective user ID to its saved set-user-ID.</P>
<blockquote>
<p class="docText">Both <tt>setreuid</tt> and <tt>setregid</tt> are XSI extensions in the Single UNIX Specification. As such, all UNIX System implementations are expected to provide support for them.</P>
<p class="docText">4.3BSD didn't have the saved set-user-ID feature described earlier. It used <tt>setreuid</tt> and <tt>setregid</tt> instead. This allowed an unprivileged user to swap back and forth between the two values. Be aware, however, that when programs that used this feature spawned a shell, they had to set the real user ID to the normal user ID before the <tt>exec</tt>. If they didn't do this, the real user ID could be privileged (from the swap done by <tt>setreuid</tt>) and the shell process could call <tt>setreuid</tt> to swap the two and assume the permissions of the more privileged user. As a defensive programming measure to solve this problem, programs set both the real user ID and the effective user ID to the normal user ID before the call to <tt>exec</tt> in the child.</p>
</blockquote>

<a name="ch08lev2sec3"></a>
<h4 class="docSection2Title"><tt>seteuid</tt> and <tt>setegid</tt> Functions</h4>
<p class="docText"><a name="idd1e58969"></a><a name="idd1e58974"></a><a name="idd1e58979"></a><a name="idd1e58984"></a><a name="idd1e58989"></a><a name="idd1e58996"></a><a name="idd1e59001"></a><a name="idd1e59008"></a><a name="idd1e59013"></a>POSIX.1 includes the two functions <tt>seteuid</tt> and <tt>setegid</tt>. These functions are similar to <tt>setuid</tt> and <tt>setgid</tt>, but only the effective user ID or effective group ID is changed.</p>
<a name="inta285"></a><P><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="500"></colgroup><thead></thead><tr><TD class="docTableCell" align="left" valign="top"><p class="docText">
<pre>
#include &lt;unistd.h&gt;

int seteuid(uid_t <span class="docEmphItalicAlt">uid</span>);

int setegid(gid_t <span class="docEmphItalicAlt">gid</span>);
</pre><br>

</P></td></tr><tr><td class="docTableCell" align="right" valign="top"><p class="docText">Both return: 0 if OK, 1 on error</p></td></tr></table></p><br>
<p class="docText">An unprivileged user can set its effective user ID to either its real user ID or its saved set-user-ID. For a privileged user, only the effective user ID is set to <span class="docEmphasis">uid</span>. (This differs from the <tt>setuid</tt> function, which changes all three user IDs.)</p>
<p class="docText"><a class="docLink" href="#ch08fig19">Figure 8.19</a> summarizes all the functions that we've described here that modify the three user IDs.</p>
<a name="ch08fig19"></a><p><center>
<h5 class="docFigureTitle">Figure 8.19. Summary of all the functions that set the various user IDs</h5>
<p class="docText"><div class="v1"><a target="_self" href="images/0201433079/graphics/08fig19_alt.gif;423615">[View full size image]</a></div><img border="0" alt="" width="500" height="269" SRC="images/0201433079/graphics/08fig19.gif;423615"></p>
</center></p><br>

<a name="ch08lev2sec4"></a>
<H4 class="docSection2Title">Group IDs</H4>
<p class="docText">Everything that we've said so far in this section also applies in a similar fashion to group IDs. The supplementary group IDs are not affected by <tt>setgid</tt>, <tt>setregid</tt>, or <tt>setegid</tt>.</p>


<UL></UL></TD></tr></table>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/team.gif" width="60" height="17" border="0" align="absmiddle"  alt="Team BBL"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=ch08lev1sec10.html><img src="images/prev.gif" width="60" height="17" border="0" align="absmiddle" alt="Previous Page"></a>
<a href=ch08lev1sec12.html><img src="images/next.gif" width="60" height="17" border="0" align="absmiddle" alt="Next Page"></a>
</div></td></tr></table>
</body></html><br>
<table width="100%" cellspacing="0" cellpadding="0"
style="margin-top: 0pt; border-collapse: collapse;"> 
<tr> <td align="right" style="background-color=white; border-top: 1px solid gray;"> 
<a href="http://www.zipghost.com/" target="_blank" style="font-family: Tahoma, Verdana;
 font-size: 11px; text-decoration: none;">The CHM file was converted to HTM by Trial version of <b>ChmD<!--110-->ecompiler</b>.</a>
</TD>
</TR><tr>
<td align="right" style="background-color=white; "> 
<a href="http://www.etextwizard.com/download/cd/cdsetup.exe" target="_blank" style="font-family: Tahoma, Verdana;
 font-size: 11px; text-decoration: none;">Download <b>ChmDec<!--110-->ompiler</b> at: http://www.zipghost.com</a>
</TD></tr></table>
